# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import time
from collections import OrderedDict

import odoo.addons.decimal_precision as dp
from odoo import api, fields, models
from datetime import datetime, timedelta
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools import float_compare, float_is_zero
from odoo.tools.translate import _
from odoo import tools, SUPERUSER_ID
from odoo.exceptions import UserError, AccessError
from odoo.exceptions import ValidationError
import calendar as cal


class resource_calendar_order(models.Model):
    _name = 'resource.calendar.order'

    name = fields.Char(u'名称', required=True)
    order_start_date = fields.Date(u'区间开始时间')
    order_end_date = fields.Date(u'区间结束时间')
    cost_frequency = fields.Selection([('daily', u'天'), ('weekly', u'周'), ('monthly', u'月'), ('yearly', u'年')],
                                      u'工作时间创建维度', default='weekly')
    calendar_lines = fields.One2many('resource.calendar', 'order_id', u'工作时间')

    dayofweek = fields.Selection([
        ('0', 'Monday'),
        ('1', 'Tuesday'),
        ('2', 'Wednesday'),
        ('3', 'Thursday'),
        ('4', 'Friday'),
        ('5', 'Saturday'),
        ('6', 'Sunday')
    ], u'星期', required=True, index=True, default='0')


    # # 获得时间对应的日期
    # @api.model
    # def _get_datetime_to_date(self, datetime_in_date):
    #     year = datetime_in_date.year
    #     month = datetime_in_date.month
    #     month += month_number
    #     while month < 0:
    #         month += 12
    #         year -= 1
    #     while month > 12:
    #         month -= 12
    #         year += 1
    #     last_start_date = datetime(year, month, 1)
    #     d = cal.monthrange(year, month)
    #     last_end_date = datetime(year, month, d[1])
    #     return last_start_date, last_end_date
    # @api.model
    # def _get_next_num_month(self, today, month_num):
    #     if not today:
    #         today = datetime.today()
    #     year = today.year
    #     month = today.month
    #     if month + month_num > 12:
    #         month = month + month_num - 12
    #         year += 1
    #     else:
    #         month += month_num
    #     start_date = datetime(year, month, 1)
    #     d = cal.monthrange(year, month)
    #     end_date = datetime(year, month, d[1])
    #     return start_date, end_date

    # 通过给与的时间，得到给与时间的月末时间，用来自动计算月末onchange
    @api.model
    def onchange_data_for_month_end(self, start_month):
        if not start_month:
            return None
        start_month = datetime.strptime(start_month, DEFAULT_SERVER_DATE_FORMAT)
        year = start_month.year
        month = start_month.month
        d = cal.monthrange(year, month)
        end_month = datetime(year, month, d[1])
        return end_month

    @api.multi
    def button_cancel_calendar(self):
        calendar_obj = self.env['resource.calendar']
        for oder in self:
            calendar_obj.search([('order_id', '=', oder.id)]).unlink()

    @api.multi
    def button_create_calendar(self):
        calendar_obj = self.env['resource.calendar']
        attendances_obj = self.env['resource.calendar.attendance']
        for order in self:
            attendances = []
            start_date_activity = datetime.strptime(order.order_start_date, DEFAULT_SERVER_DATE_FORMAT)
            end_date_activity = datetime.strptime(order.order_end_date, DEFAULT_SERVER_DATE_FORMAT)
            current_date = start_date_activity
            # 先通过日期生成所有的日期资源
            # 然后通过设置周，月等，来进行分组。
            # 因为日期必须要有工作时间对象，所以先生成一个，最后删除
            unlink_calendar = calendar_obj.create({
                'name': order.name + u"[天]",
                'order_id': order.id,
            })
            while current_date <= end_date_activity:
                current_date_string = datetime.strftime(current_date, DEFAULT_SERVER_DATE_FORMAT)
                attendance = attendances_obj.create({
                    'calendar_id': unlink_calendar.id,
                    'name': current_date_string,
                    'hour_from': 8.0,
                    'hour_to': 18.0,
                    'date_from': current_date_string,
                    'date_to': current_date_string,
                    'dayofweek': str(current_date.weekday())
                })
                current_date += timedelta(days=1)
                attendances.append(attendance)
            if attendances and order.cost_frequency <> 'daily':
                last_week = None
                for attendance in attendances:
                    date_from_time = datetime.strptime(attendance.date_from, DEFAULT_SERVER_DATE_FORMAT)
                    # 因为周数,在每年的年初时会重置,比如2018-12-31,这天实际上试2018年,但周序列是2019年的1.所以下面部分代码就是解决这个问题.
                    # 如果周序列为1,那么就要检查所属的年,如果年没有跨,那么周序列就+1
                    year = str(date_from_time.year)
                    month_num = str(date_from_time.month)
                    week_num = str(date_from_time.isocalendar()[1])

                    if order.cost_frequency == 'weekly':
                        # 上次周数赋值
                        if not last_week:
                            last_week = week_num
                        day_num = str(date_from_time.day)
                        # 如果当前天大于20,而周居然是1,那就肯定是跨了.这时自动加一周
                        if week_num == str(1) and int(day_num) > 20:
                            week_num = str(int(last_week) + 1)
                        else:
                            last_week = week_num
                        name = year + u"年" + week_num + u"周"
                    elif order.cost_frequency == 'monthly':
                        name = year + u"年" + month_num + u"月"
                    elif order.cost_frequency == 'yearly':
                        name = year + u"年"

                    calendar = calendar_obj.search([('name', '=', name)])
                    if not calendar:
                        calendar = calendar_obj.create({
                            'name': name,
                            'order_id': order.id,
                        })
                    else:
                        calendar = calendar[0]
                    attendance.calendar_id = calendar.id
                unlink_calendar.unlink()
        calendar_obj.button_dayofwork_start()

    @api.multi
    def set_day_of_work(self):
        for order in self:
            for calendar in order.calendar_lines:
                for attendance in calendar.attendance_ids:
                    if attendance.dayofweek == order.dayofweek:
                        attendance.dayofwork = True

    @api.multi
    def set_day_of_unwork(self):
        for order in self:
            for calendar in order.calendar_lines:
                for attendance in calendar.attendance_ids:
                    if attendance.dayofweek == order.dayofweek:
                        attendance.dayofwork = False


class resource_calendar(models.Model):
    _inherit = ['resource.calendar']

    # 获得工作时间开始，方便在计划中进行过滤
    @api.model
    def _get_lines_start_date(self):
        for att in self:
            if att.attendance_ids:
                att.dayofwork_start = att.attendance_ids[0].date_from

    dayofwork_start = fields.Date(u'工作开始时间', compute='_get_lines_start_date', store=True)
    order_id = fields.Many2one('resource.calendar.order', u'来源单据')


    # 计算给定时间的月初月末日期。
    @api.model
    def _get_next_num_month(self, datetime_in_date, month_number):
        year = datetime_in_date.year
        month = datetime_in_date.month
        month += month_number
        while month <= 0:
            month += 12
            year -= 1
        while month > 12:
            month -= 12
            year += 1
        last_start_date = datetime(year, month, 1)
        d = cal.monthrange(year, month)
        last_end_date = datetime(year, month, d[1])
        return last_start_date, last_end_date

    @api.model
    def button_dayofwork_start(self):
        calendars = self.env['resource.calendar'].search([])
        for calendar in calendars:
            calendar.dayofwork_start = calendar.attendance_ids[0].date_from

    @api.model
    def month_split_week_line(self, start_date, end_date):
        attendance_obj = self.env['resource.calendar.attendance']
        res = []
        if start_date and end_date:
            weeks = []
            # 先找到区间所有工作时间
            attendances = attendance_obj.search(
                [('date_from', '>=', start_date), ('date_from', '<=', end_date),
                 ('dayofwork', '=', True)], order='date_from')
            # 再通过所有工作时间找到对应的周，并去重复
            for attendance in attendances:
                if attendance.calendar_id not in weeks:
                    weeks.append(attendance.calendar_id)
            for week in weeks:
                line_start_date = None
                line_end_date = None
                # 周的最开始有效时间，与最后有效时间
                min_date_from = None
                max_date_from = None
                # 循环每一天，来进行开始时间与结束时间赋值
                for day in week.attendance_ids:
                    # 如果是工作时间,就是有效时间，可以进行判断
                    if day.dayofwork:
                        # 如果有时间和开始时间相同，自然是开始时间了
                        if day.date_from == start_date:
                            line_start_date = start_date
                        # 如果有时间和结束时间相同,自然就是结束时间
                        if day.date_from == end_date:
                            line_end_date = end_date
                        # 如果有最小时间,且最小时间比当前循环的时间大,就需要重新调整最小时间
                        if min_date_from and min_date_from >= day.date_from:
                            min_date_from = day.date_from
                        elif not min_date_from:
                            min_date_from = day.date_from
                        # 如果有最大时间,且最大时间比当前循环的时间小,就需要重新调整最大时间
                        if max_date_from and max_date_from <= day.date_from:
                            max_date_from = day.date_from
                        elif not max_date_from:
                            max_date_from = day.date_from
                # 如果本周里面没有最小时间,那么最小时间就是最小时间
                if not line_start_date:
                    line_start_date = min_date_from
                if not line_end_date:
                    line_end_date = max_date_from

                res_dic = {
                    'start_date': line_start_date,
                    'end_date': line_end_date,
                    'resource_calendar': week.id,
                }
                start_date_activity = datetime.strptime(line_start_date, DEFAULT_SERVER_DATE_FORMAT)
                end_date_activity = datetime.strptime(line_end_date, DEFAULT_SERVER_DATE_FORMAT)
                days = end_date_activity - start_date_activity
                # 时间相减得到时间,days得到天数
                res_list = (res_dic, days.days + 1)
                res.append(res_list)
        return res, len(attendances)


class resource_calendar_attendance(models.Model):
    _inherit = ['resource.calendar.attendance']

    dayofwork = fields.Boolean(u'工作时间', default=True)
